#include "udpsr.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h>
#include "commom.h"

 tcp_udp tcp_udp_info;
UdpSR::UdpSR()
{

}

int UdpSR::rbcp(char *cmdStr, char *sndHeaderAddr, char *pSendData)
{
    char* udpAddr;
    unsigned int udpPort;

    RbcpHeader sndHeader;

	//printf("rbcp is ok \n");
	udpPort = UDP_PORT ; //8080

        udpAddr = UDP_IP ;
  //   printf("udpAddr is %s \n", udpAddr);
    
   // printf("udpAddr is %s, UDP_PORT is %d",UDP_IP,  UDP_PORT);
    sndHeader.type=RBCP_VER;  //0XFF
    sndHeader.id=1;
	//int judge = 0;
    int judge=dispatchCommand(cmdStr, sndHeaderAddr, pSendData, udpAddr, udpPort, &sndHeader,1);

    return judge;
}

unsigned int UdpSR::myAtoi(char *str)
{
    unsigned char temp[256];
    int i=0, j=0, value=0, endProc=0;
    strcpy((char *)temp,str);
    #if 0
	printf("\n");
	for(int ii=0; ii<256;ii++) {
		printf("ii=[%x] ",temp[ii]);
		}

	printf("\n");
    #endif

    if((temp[i]=='0')||isblank(temp[i]))
        i++;
    if((temp[i]=='x')||(temp[i]=='X'))
    {
        i++;
        j++;
        while((endProc==0)&&(temp[i]!='\0'))
        {
			
            if(isdigit(temp[i]))
            {
                value=value*16;
                value+=temp[i]-'0';
                i++;
            }
            else if(isxdigit(temp[i]))
            {
                value=value*16;

                if(isupper(temp[i]))
                {
                    value+=temp[i]-'A'+10;
                }
                else
                {
                    value+=temp[i]-'a'+10;
                }
                i++;
            }
            else
            {
                endProc=1;
                //  puts("endProc");
            }
        }
        if(j>8)
        {
            puts("Error: too large value is detected.");
            return 0xFFFFFFFF;
        }
    }
    else
    {
        while(isdigit(temp[i]))
        {
            value=value*10;
            value+=temp[i]-'0';
            i++;
            j++;
            if(j>10)
            {
                puts("Error: too large value is detected.");
                return 0xFFFFFFFF;
            }
        }
    }

    return value;
}

int UdpSR::rbcp_com(char *udpAddr, unsigned int udpPort, RbcpHeader *sendHeader, char *sendData, char *recvData, char dispMode)
{
    struct sockaddr_in sitcpAddr;
    int sock;

    struct timeval timeout;
    fd_set setSelect;

    int sndDataLen;
    int cmdPckLen;

    char sndBuf[1024];
    int i, j = 0;
    int rcvdBytes;
    char rcvdBuf[1024];
    int numReTrans =0;

    //WORD socketVersion = MAKEWORD(2,2);
   // WSADATA wsaData;

    /* Create a Socket */
    if(dispMode==RBCP_DISP_MODE_DEBUG)     //RBCP_DISP_MODE_DEBUG=2
        puts("\nCreate socket...\n");

    sock = socket(AF_INET, SOCK_DGRAM, 0);
    sitcpAddr.sin_family      = AF_INET;
    sitcpAddr.sin_port        = htons(udpPort);
    sitcpAddr.sin_addr.s_addr = inet_addr(udpAddr);
    //sitcpAddr.sin_addr.S_un.S_addr = inet_addr(udpAddr);
    // printf("udpPort:\n",udpPort);
	//printf("udpAddr:\n",udpAddr);
	
    sndDataLen = (int)sendHeader->length;
    if(dispMode==RBCP_DISP_MODE_DEBUG)
    printf(" Length = %i\n",sndDataLen);

    /* Copy header data */
    memcpy(sndBuf,sendHeader, sizeof(RbcpHeader));
    if(sendHeader->command==RBCP_CMD_WR)
    {
        memcpy(sndBuf+sizeof(RbcpHeader),sendData,sndDataLen);
        cmdPckLen=sndDataLen + sizeof(RbcpHeader);
    }
    else
    {
        cmdPckLen=sizeof(RbcpHeader);
    }

    if(dispMode==RBCP_DISP_MODE_DEBUG)
    {
        for(i=0; i< cmdPckLen;i++)
        {
            if(j==0)
            {
                printf("\t[%.3x]:%.2x ",i,(unsigned char)sndBuf[i]);
                j++;
            }
            else if(j==3)
            {
                printf("%.2x\n",(unsigned char)sndBuf[i]);
                j=0;
            }
            else
            {
                printf("%.2x ",(unsigned char)sndBuf[i]);
                j++;
            }
        }
        if(j!=3)
            printf("\n");
    }

    /* send a packet*/
    sendto(sock, sndBuf, cmdPckLen, 0, (struct sockaddr *)&sitcpAddr, sizeof(sitcpAddr));
    if(dispMode==RBCP_DISP_MODE_DEBUG)
        puts("The packet have been sent!\n");

    /* Receive packets*/

    if(dispMode==RBCP_DISP_MODE_DEBUG)
        puts("\nWait to receive the ACK packet...");

    while(numReTrans<3)
    {
        FD_ZERO(&setSelect);
        FD_SET(sock, &setSelect);

        timeout.tv_sec  = 0;
        timeout.tv_usec = 10000;

        if(select(sock+1, &setSelect, NULL, NULL,&timeout)==0)
        {
            /* time out */
            puts("\n***** Timeout ! *****");
            sendHeader->id++;
            memcpy(sndBuf,sendHeader, sizeof(RbcpHeader));
            sendto(sock, sndBuf, cmdPckLen, 0, (struct sockaddr *)&sitcpAddr, sizeof(sitcpAddr));
            numReTrans++;
            FD_ZERO(&setSelect);
            FD_SET(sock, &setSelect);
        }
        else
        {
        /* receive packet */
            if(FD_ISSET(sock,&setSelect))
            {
                rcvdBytes=recvfrom(sock, rcvdBuf, 2048, 0, NULL, NULL);

                if(rcvdBytes<sizeof(RbcpHeader))
                {
                    puts("ERROR: ACK packet is too short");
                    close(sock);
                    return -1;
                }

                if((0x0f & rcvdBuf[1])!=0x8)
                {
                    puts("ERROR: Detected bus error");
                    close(sock);
                    return -1;
                }

                rcvdBuf[rcvdBytes]=0;

                if(RBCP_CMD_RD)
                {
                    memcpy(recvData,rcvdBuf+sizeof(RbcpHeader),rcvdBytes-sizeof(RbcpHeader));
                }

                if(dispMode==RBCP_DISP_MODE_DEBUG)
                {
                    puts("\n***** A pacekt is received ! *****.");
                    puts("Received data:");

                    j=0;

                    for(i=0; i<rcvdBytes; i++)
                    {
                        if(j==0)
                        {
                            printf("\t[%.3x]:%.2x ",i, sendHeader,(unsigned char)rcvdBuf[i]);
                            j++;
                        }
                        else if(j==3)
                        {
                            printf("%.2x\n",(unsigned char)rcvdBuf[i]);
                            j=0;
                        }
                        else
                        {
                            printf("%.2x ",(unsigned char)rcvdBuf[i]);
                            j++;
                        }
                        if(i==7)
                            printf("\n Data:\n");
                    }

                    if(j!=3)
                        puts(" ");
                }
                else if(dispMode==RBCP_DISP_MODE_INTERACTIVE)//RBCP_DISP_MODE_INTERACTIVE=1
                {
                    if(sendHeader->command==RBCP_CMD_RD)   //RBCP_CMD_RD=0xC0
                    {
                        j=0;
                        puts(" ");

                        for(i=8; i<rcvdBytes; i++)
                        {
                            if(j==0)
                            {
                                printf(" [0x%.8x] %.2x ",ntohl(sendHeader->address)+i-8,(unsigned char)rcvdBuf[i]);
                                j++;
                            }
                            else if(j==7)
                            {
                                printf("%.2x\n",(unsigned char)rcvdBuf[i]);
                                j=0;
                            }
                            else if(j==4)
                            {
                                printf("- %.2x ",(unsigned char)rcvdBuf[i]);
                                j++;
                            }
                            else
                            {
                                printf("%.2x ",(unsigned char)rcvdBuf[i]);
                                j++;
                            }
                        }

                        if(j!=15)
                            puts(" ");
                    }
                    else
                    {
                        printf(" 0x%x: OK\n",ntohl(sendHeader->address));
                    }
                }
                numReTrans = 4;
                close(sock);
                return(rcvdBytes);
            }
        }
    }
   close(sock);

    return -3;
}

/* cmdStr  : wrb(), wrs(), wrw(), rd()
 * pszArg1  :
 * pSendData  :
 * udpAddr   :
 * udpPort :
 * sndHeader:
 * dispMode :
 */

int UdpSR::dispatchCommand(char *cmdStr, char *sndHeaderAddr, char *pSendData, char *udpAddr, unsigned int udpPort, RbcpHeader *sndHeader, char dispMode)
{
    char recvData[UDP_BUF_SIZE];

    unsigned int tempInt;
	//printf("cmdStr is %s sndHeaderAddr is%s, udpAddr is %s, pSendData is %d, %d\n", cmdStr, sndHeaderAddr, udpAddr,pSendData[0], udpPort);
	
#if 1
    if(strcmp(cmdStr, "wrb") == 0)
    {
		//printf("pSendData is %s",pSendData);
        tempInt = myAtoi(pSendData);  // 把 pSendData 指向的字符串所表示的数转化为无符号整型
		//printf("tempInt is %d",tempInt);
        //pSendData[0] = (char)(0xFF & tempInt);
#if 1		
		//printf("pSendData[0] is:%d\n",pSendData);
        sndHeader->command= RBCP_CMD_WR;  //RBCP_CMD_WR=0x80
        sndHeader->length=1;
        sndHeader->address=htonl(myAtoi(sndHeaderAddr));
        //printf("myAtoi(sndHeaderAddr) is %d",myAtoi(sndHeaderAddr));
		//printf("cmdStr is %s, sndHeaderAddr is %s, pSendData is %s", cmdStr, sndHeaderAddr, pSendData);
        ///qDebug()<<"pszVerv is:"<<cmdStr<<sndHeaderAddr<<pSendData;
  //      qDebug()<<"pSendData is:"<<pSendData;
		//printf("pSendData is %s", pSendData);
//        qDebug()<<"dispMode is:"<<dispMode;
		//printf("dispMode is %d", dispMode);

        return rbcp_com(udpAddr, udpPort, sndHeader, pSendData,recvData,dispMode);
#else 
	return 0;
#endif
    }
    else if(strcmp(cmdStr, "wrs") == 0)
    {
        tempInt = myAtoi(pSendData);
        pSendData[1]= (char)(0xFF & tempInt);
        pSendData[0]= (char)((0xFF00 & tempInt)>>8);

        sndHeader->command= RBCP_CMD_WR;
        sndHeader->length=2;
        sndHeader->address=htonl(myAtoi(sndHeaderAddr));

        return rbcp_com(udpAddr, udpPort, sndHeader, pSendData,recvData,dispMode);
    }
    else if(strcmp(cmdStr, "wrw") == 0)
    {
        tempInt = myAtoi(pSendData);

        pSendData[3]= (char)(0xFF & tempInt);
        pSendData[2]= (char)((0xFF00 & tempInt)>>8);
        pSendData[1]= (char)((0xFF0000 & tempInt)>>16);
        pSendData[0]= (char)((0xFF000000 & tempInt)>>24);

        sndHeader->command= RBCP_CMD_WR;
        sndHeader->length=4;
        sndHeader->address=htonl(myAtoi(sndHeaderAddr));

        return rbcp_com(udpAddr, udpPort, sndHeader, pSendData,recvData,dispMode);
    }
    else if(strcmp(cmdStr, "rd") == 0)
    {
        sndHeader->command= RBCP_CMD_RD;
        sndHeader->length=myAtoi(pSendData);
        sndHeader->address=htonl(myAtoi(sndHeaderAddr));

        return rbcp_com(udpAddr, udpPort, sndHeader, pSendData,recvData,dispMode);
    }
#endif
    return 0;
}

